home *** CD-ROM | disk | FTP | other *** search
- #include <stddef.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <osbind.h>
- #include <memory.h>
- #include <time.h>
- #include <fcntl.h>
- #include <string.h>
- #include "symdir.h"
- #include <unistd.h>
- #include "lib.h"
- #include <ctype.h>
-
- int errno;
- int __mint; /* 0 for TOS, MiNT version number otherwise */
- int _console_dev;
-
- FILE _iob[_NFILE]; /* stream buffers initialized below */
-
- /* functions registered by user for calling at exit */
- #ifdef __STDC__
- typedef void (*ExitFn)(void);
- #else
- typedef void (*ExitFn)();
- #endif
- static ExitFn *_at_exit;
- static int num_at_exit; /* number of functions registered - 1 */
- extern clock_t _start_time; /* defined in clock.c */
- extern clock_t _child_runtime; /* defined in spawnve.c */
- extern clock_t _sys_runtime; /* defined in spawnve.c */
-
- /*
- * get MiNT version number
- */
- static void
- getMiNT(void)
- {
- long *cookie;
-
- cookie = *((long **) 0x5a0L);
- if (!cookie)
- __mint = 0;
- else {
- while (*cookie) {
- if (*cookie == 0x4d694e54L) {
- __mint = cookie[1];
- return;
- }
- cookie += 2;
- }
- }
- __mint = 0;
- }
-
- /* supplied by the user */
- __EXTERN int main __PROTO((int, char **, char **));
-
- /* in getbuf.c */
- __EXTERN void _getbuf __PROTO((FILE *));
-
- #if __GNUC__ > 1
- /* in libgcc2.c */
- __EXTERN void __do_global_dtors __PROTO ((void));
- #endif
-
- void
- _main(_argc, _argv, _envp)
- long _argc;
- char **_argv, **_envp;
- {
- char *tty;
- register FILE *f;
- register int i;
- char *s, *t;
- extern int __default_mode__; /* in defmode.c or defined by user */
- int main(int, char **, char **);
-
- /* clear isatty status for dumped programs */
- for (i = 0; i < __NHANDLES; i++)
- __open_stat[i].status = FH_UNKNOWN;
- _start_time = 0; /* for dumped prgs */
-
- _start_time = clock();
- _child_runtime = _sys_runtime = 0;
- num_at_exit = 0;
- /*
- * check for MiNT
- */
- (void)Supexec(getMiNT);
-
- /*
- * check environment for various things
- */
- _set_unixmode(getenv("UNIXMODE"));
-
- if (tty = getenv("TTY")) {
- if (!strcmp(tty, "AUX:") || !strcmp(tty, "aux:"))
- _console_dev = 1;
- else
- _console_dev = 2;
- }
- else
- _console_dev = 2;
-
- /* if stderr is not re-directed to a file, force 2 to console
- * (UNLESS we've been run from a shell we trust, i.e. one that supports
- * the official ARGV scheme, in which case we leave stderr be).
- */
- if(!*_argv[0] && isatty(2))
- (void)Fforce(2, _console_dev - 3);
-
- stdin->_flag = _IOREAD|_IOFBF|__default_mode__;
- stdout->_flag = _IOWRT|_IOLBF|__default_mode__;
- stderr->_flag = _IORW|_IONBF|__default_mode__;
- /* some brain-dead people read from stderr */
-
- for(i = 0, f = _iob; i < 3; ++i, ++f) { /* flag device streams */
- if(isatty(f->_file = i))
- f->_flag |= _IODEV;
- else
- if(f == stdout) { /* stderr is NEVER buffered */
- /* if stdout re-directed, make it full buffered */
- f->_flag &= ~(_IOLBF | _IONBF);
- f->_flag |= _IOFBF;
- }
- _getbuf(f); /* get a buffer */
- }
-
- for(i = 0; i <= 2; i++) {
- __open_stat[__OPEN_INDEX(i)].filename = isatty(i) ?
- ((_console_dev == 2) ? "/dev/console" : "/dev/tty1")
- : (char *)NULL; /* if it was re-dir */
- }
-
- for(i = 3; i < _NFILE; i++, f++) {
- f->_flag = 0; /* clear flags, if this is a dumped program */
- }
-
- /* Fix up environment, if necessary. At present, the only variable
- * affected is PATH; the "standard" path separators for PATH are
- * ',' and ';' in the Atari world, but POSIX mandates ':'. This
- * conflicts with the use of ':' as a drive separator, so we
- * also convert names like A:\foo to /dev/A/foo
- * NOTE: this conversion must be undone in spawn.c so that
- * old fashioned programs will understand us!
- */
- for (i = 0; s = _envp[i]; i++) { /* '=', NOT '==' */
- if (s[0] == 'P' && s[1] == 'A' && s[2] == 'T' &&
- s[3] == 'H' && s[4] == '=') {
- _envp[i] = (char *)malloc(4 * strlen(s));
- strncpy(_envp[i], s, 5);
- t = _envp[i]+5;
- s += 5;
- while (*s) {
- if (s[1] == ':' && isalpha(*s)) { /* drive letter */
- *t++ = '/';
- *t++ = 'd'; *t++ = 'e'; *t++ = 'v';
- *t++ = '/'; *t++ = *s++; s++;
- } else if (*s == ';' || *s == ',') {
- *t++ = ':'; s++;
- } else {
- *t++ = *s++;
- }
- }
- *t++ = 0;
- break;
- }
- }
-
- errno = 0;
-
- /* ANSI-Draft: A return from the initial call to the main */
- /* function is equivalent to calling the exit function with */
- /* the value returned by the main function as its argument. If */
- /* the main function executes a return that specifies no */
- /* value, the termination status returned to the host */
- /* environment is undefined. [section 2.1.2.2] */
- exit(main((int) _argc, _argv, _envp)); /* if main() returns exit */
- }
-
- __EXITING _exit(status)
- int status;
- {
- __exit((long)status);
- }
-
- /* For debuggers: non-macro versions of std{in,out,err}. */
- #undef stdin
- #undef stdout
- #undef stderr
- FILE *stdin = &_iob[0];
- FILE *stdout = &_iob[1];
- FILE *stderr = &_iob[2];
-
- __EXITING exit(status)
- int status;
- {
- register int i, f;
-
-
- #if __GNUC__ > 1
- __do_global_dtors ();
- #endif
-
- for(i=0; i<_NFILE; ++i) {
- f = _iob[i]._flag;
- if(f & (_IORW | _IOREAD | _IOWRT))
- if (_iob[i]._file <= 2) /* only flush std. streams */
- fflush(&_iob[i]);
- else
- fclose(&_iob[i]);
- }
-
- for(i = num_at_exit - 1; i >= 0; --i)
- (*_at_exit[i])();
-
- _exit(status);
- }
-
- /* register a function for execution on termination */
- /* Ansi requires atleast 32 entries, we make it dynamic and hope
- it meets the ansi requirement */
-
- int atexit(func)
- ExitFn func;
- {
- ExitFn *new_at_exit = _at_exit;
-
- if (num_at_exit == 0)
- new_at_exit = (ExitFn *)malloc((size_t)sizeof(ExitFn));
- else
- new_at_exit = (ExitFn *)realloc(new_at_exit,
- (size_t)((num_at_exit + 1) * sizeof(ExitFn)));
- if(new_at_exit == (ExitFn *)NULL)
- return -1; /* failure */
-
- _at_exit = new_at_exit;
- _at_exit[num_at_exit++] = func;
- return 0; /* success */
- }
-